package com.tencent.wxcloudrun.utils;

import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.regex.Pattern;

/**
 * 因为处理数据存在时间差,故获取当前时间则设置统一的延迟时间
 */
public class DateUtil {
    private static final Logger log = LoggerFactory.getLogger(DateUtil.class);

    public static final String DAY_FORMAT = "yyyyMMdd";
    public static final String MONTH_FORMAT = "yyyyMM";
    public static final String MONTH_FORMAT_UNDERLINE = "yyyy_MM";
    public static final String DAY_FORMAT_STRING = "yyyy-MM-dd";
    //毫秒
    public static final String MILLISECOND_FORMAT_STRING = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    //格式：秒
    public static final DateTimeFormatter SECOND_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    //格式：毫秒
    public static final DateTimeFormatter MILLISECOND_FORMATTER = DateTimeFormatter.ofPattern(MILLISECOND_FORMAT_STRING);

    private static final String PROBABLY_REGEX = "\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0|1])";
    private static final String YMD_PROBABLY_REGEX = "\\d{4}(0[1-9]|1[0-2])(0[1-9]|1[0-9]|2[0-9]|3[0|1])";


    /**
     * 负数:延迟时间,正数:提前
     */
    private static final Integer DELAY_HOUR = 0;

    /**
     * LocalDateTime 当前时间延迟
     * @return
     */
    public static LocalDateTime getLocalDateTimeNow(){
        return LocalDateTime.now().plusHours(DELAY_HOUR);
    }

    /**
     * LocalDate 当前时间延迟
     * @return
     */
    public static LocalDate getLocalDateNow(){
        LocalDateTime localDateTimeNow = getLocalDateTimeNow();
        return localDateTimeNow.toLocalDate();
    }

    /**
     * 字符串格式化为日期,字符串必须符合 yyyy-MM-dd 格式
     *
     * @param date 将要 LocalDate 化的字符串
     * @return LocalDate
     */
    public static LocalDate strToLocalDate(String date) {
        return StrUtil.isNotBlank(date) && Pattern.matches(PROBABLY_REGEX, date) ?
                LocalDate.parse(date, DateTimeFormatter.ofPattern(DAY_FORMAT_STRING)) : null;
    }

    /**
     * 字符串格式化为日期 指定格式
     * @param date
     * @param format
     * @return
     */
    public static LocalDate strToLocalDate(String date,String format) {
        try {
            return LocalDate.parse(date, DateTimeFormatter.ofPattern(format));
        }catch (RuntimeException e){
            return null;
        }
    }

    /**
     * localDateTime 转long(毫秒)
     * @param localDateTime
     * @return
     */
    public static long dateTimeToLong(LocalDateTime localDateTime){
        return localDateTime.toInstant(ZoneOffset.of(("+8"))).toEpochMilli();
    }

    /**
     * localDateTime 转long(秒)
     * @param localDateTime
     * @return
     */
    public static long dateTimeToSecond(LocalDateTime localDateTime){
        return localDateTime.toEpochSecond(ZoneOffset.of("+8"));
    }

    /**
     * localDate 转long
     * @param localDate
     * @return
     */
    public static long dateToLong(LocalDate localDate){
        return localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * long(毫秒) 转 LocalDateTime
     * @param timestamp
     * @return
     */
    public static LocalDateTime longToLocalDateTime(long timestamp){
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
    }

    /**
     * long(秒)转LocalDateTime
     * @param timestamp
     * @return
     */
    public static LocalDateTime secondToLocalDateTime(long timestamp){
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
    }

    /**
     * 将字符串的时间戳转换为LocalDateTime
     * 获取上次执行的时间
     * @param srcLastTime
     * @return
     */
    public static LocalDateTime getLastTime(String srcLastTime) {
        LocalDateTime localDateTime = null;
        if (StrUtil.isBlank(srcLastTime)) {
            return localDateTime;
        }
        //value 不是数字
        if (!isInteger(srcLastTime)) {
            log.error("上次执行任务的时间({})格式一次:",srcLastTime);
            return localDateTime;
        }
        localDateTime = DateUtil.longToLocalDateTime(Long.valueOf(srcLastTime));
        return localDateTime;
    }

    /*
     * 判断是否为整数，str为空("",null," " )表示第一次,返回true
     * @param str 传入的字符串
     * @return 是整数返回true,否则返回false
     */
    public static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 获取一个月前的日期
     * @return
     */
    public static LocalDate getOneMonthAgoLocalDate(){
        return LocalDate.now().plusMonths(-1);
    }

    /**
     * LocalDate 转换为yyyyMMdd格式的字符串日期
     * @param localDate
     * @return
     */
    public static String convertLocalDateToStr(LocalDate localDate){
        if(null == localDate){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        return localDate.format(formatter);
    }

    public static String convertLocalDateToStr(LocalDate localDate,String format){
        if(null == localDate){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return localDate.format(formatter);
    }

    /**
     * LocalDateTime 转换为yyyy-MM-dd HH:mm:ss.SSS格式
     * @param localDateTime
     * @return
     */
    public static String convertLocalDateToStr(LocalDateTime localDateTime){
        if(null == localDateTime){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        return localDateTime.format(formatter);
    }

//    /**
//     * 转换为秒字符串
//     * @param localDateTime
//     * @return
//     */
//    public static String convertSecondStr(LocalDateTime localDateTime){
//        if(null == localDateTime){
//            return null;
//        }
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//        return localDateTime.format(formatter);
//    }

    /**
     * 将yyyyMMdd格式的日期转换为LocalDate
     * @param localDate
     * @return
     */
    public static LocalDate convertStrToLocalDate(String localDate){
        if(StrUtil.isBlank(localDate)){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate parse = LocalDate.parse(localDate, formatter);
        return parse;
    }

    /**
     * 转换LocalDateTime
     * @param time
     * @param format
     * @return
     */
    public static LocalDateTime parseStringToDateTime(String time, String format) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(time, df);
    }

    /**
     *  localDateTime转换Date
     * @param localDateTime
     * @return
     */
    public static Date convertDate(LocalDateTime localDateTime){
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 时间戳转日期(默认格式)
     *
     * @author fzr
     * @param time 时间戳
     * @return String
     */
    public static String timestampToDate(Long time) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000));
    }

    /**
     * 毫秒转字符串("yyyy-MM-dd HH:mm:ss.SSS")
     * @param timestamp  毫秒时间戳
     * @return
     */
    public static String longToStr(long timestamp){
        String tmp = String.valueOf(timestamp);
        if(tmp.length() == 10){
            timestamp = timestamp*1000;
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
        return convertLocalDateToStr(localDateTime);
    }

    /**
     * 获取指定日期所在星期一的日期
     * @param localDate
     * @return
     */
    public static String getMondayThisWeek(LocalDate localDate){
        LocalDate mondayThisWeek = localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        return convertLocalDateToStr(mondayThisWeek);
    }

    /**
     * 获取指定日期所在星期一的日期
     * @param localDate
     * @return
     */
    public static LocalDate getMonday(LocalDate localDate){
        return localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
    }

    /**
     * 获取指定日期所在星期一的日期
     * @param localDate
     * @return
     */
    public static LocalDate getLastMonday(LocalDate localDate){
        return localDate.minusWeeks(1).with(DayOfWeek.MONDAY); // 获取上一周的星期一
    }

    /**
     * 获取星期天
     * @param localDate
     * @return
     */
    public static LocalDate getSunday(LocalDate localDate){
        return localDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
    }

    /**
     * 判断是否是星期一
     * @param localDate
     * @return
     */
    public static Boolean isMonday(LocalDate localDate){
        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
        if (dayOfWeek == DayOfWeek.MONDAY) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 时差(小时)
     * @param startTime
     * @param endTime
     * @return
     */
    public static long diffHours(LocalDateTime startTime,LocalDateTime endTime){
        return ChronoUnit.HOURS.between(startTime, endTime);
    }
    /**
     * 时差(分钟)
     * @param startTime
     * @param endTime
     * @return
     */
    public static long diffMinutes(LocalDateTime startTime,LocalDateTime endTime){
        return ChronoUnit.MINUTES.between(startTime, endTime);
    }

    /**
     * 时差(秒)
     * @param startTime
     * @param endTime
     * @return
     */
    public static long diffSeconds(LocalDateTime startTime,LocalDateTime endTime){
        return ChronoUnit.SECONDS.between(startTime, endTime);
    }

    /**
     * 判断是否是1号
     * @param localDate
     * @return
     */
    public static Boolean isDayOfMonth(LocalDate localDate){
        if (localDate.getDayOfMonth() == 1) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

    /**
     * 获取月初时间
     * @param localDate
     * @return
     */
    public static LocalDateTime getFirstDayOfMonth(LocalDate localDate){
        LocalDate firstDayOfMonth = localDate.with(TemporalAdjusters.firstDayOfMonth());// 本月第一天
        return firstDayOfMonth.atStartOfDay(); // 获取月初时间（默认为午夜00:00）
    }

    /**
     * 获取月末时间
     * @param localDate
     * @return
     */
    public static LocalDateTime getLastDayOfMonth(LocalDate localDate){
        LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth());//本月最后一天
        return lastDayOfMonth.atTime(LocalTime.MAX); // 获取月末时间
    }

    /**
     * 计算年龄
     * @param birthDate
     * @return
     */
    public static int calculateAge(LocalDate birthDate) {
        LocalDate today = LocalDate.now();
        Period period = Period.between(birthDate, today);
        return period.getYears();
    }

    /**
     * Date转LocalDateTime
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date){
        Instant instant = date.toInstant();
        return instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static String convertSecondsTimeToStr(LocalDateTime localDateTime){
        if(null == localDateTime){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        return localDateTime.format(formatter);
    }

    public static String convertSecondsTimeToStr2(LocalDateTime localDateTime){
        if(null == localDateTime){
            return null;
        }
        return localDateTime.format(SECOND_FORMATTER);
    }
}
